package com.example.springboot_demo.proxy.dy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.quartz.QuartzTransactionManager;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * <P> @Author: SongKeCheng
 * <P> Type: Class
 * <P> Description: JDK 动态代理
 * <P> Date: 2024/6/22:19:19
 */

@SuppressWarnings({"unchecked", ""})
public class ServiceProxyFactory {
    private static final Logger log = LoggerFactory.getLogger(ServiceProxyFactory.class);


    /**
     * 提供工厂方法：用来创建并返回代理类对象
     * 代理对象 完成数据库事务管理
     */
    public static <T> T getProxyTransaction(T obj) {
        Class<?> clazz = obj.getClass();
        ClassLoader classLoader = clazz.getClassLoader();
        Class<?>[] interfaces = clazz.getInterfaces();
        //参数1：代理对象
        //参数2：需要调用的方法
        //参数3：调用method方法时传的参数
        //返回值：调用method方法得到的结果
        //不要使用proxy 传入 method，这个是代理对象
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                log.info("开启数据库事务");

                Object result = method.invoke(obj, args);

                log.info("提交数据库事务");


                return result;
            }
        };

        //参数1：类加载器
        //参数2：被代理类(UserServiceImpl)实现的所有接口
        //参数3：处理器，拦截方法调用，执行我们自己指定的特殊代码
        Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

        return (T) proxy;
    }

    /**
     * 提供工厂方法：用来创建并返回代理类对象
     * 记录方法的执行完成时间
     */
        public static <T> T getProxyCalCallTime(T obj) {
        Class<?> clazz = obj.getClass();
        ClassLoader classLoader = clazz.getClassLoader();
        Class<?>[] interfaces = clazz.getInterfaces();
        //参数1：代理对象
        //参数2：需要调用的方法
        //参数3：调用method方法时传的参数
        //返回值：调用method方法得到的结果
        //不要使用proxy 传入 method，这个是代理对象
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                long start = System.currentTimeMillis();

                Object result = method.invoke(obj, args);

                long end = System.currentTimeMillis();

                log.info("当前方法：{},执行需要时间：{} ms", method.getName(), end - start);

                return result;
            }
        };

        //参数1：类加载器
        //参数2：被代理类(UserServiceImpl)实现的所有接口
        //参数3：处理器，拦截方法调用，执行我们自己指定的特殊代码
        Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);

        return (T) proxy;
    }

}
